<?php 

if( !defined("SITE_ID") ) {
	require_once('../accesscheck.php');
}

$fileUtils = new FileUtils();

if( isset($_POST['action']) && $_POST['action'] == "save_file" && isset($_POST['FilePath']) ) {

   $fileUtils->saveFileContent( kan_fix_path($_POST['FilePath']), $_POST['EditorContent'] );
}

if( isset($_POST['action']) && $_POST['action'] == "show_file" && $_POST['FilePath'] ) {
   $content = file_get_contents( kan_fix_path($_POST['FilePath']) );
   $mimeType = isset($_POST['mimeType']) ? $_POST['mimeType'] : 'text/php';
   $content = htmlentities($content);
   $fileUtils->getEditorForContent($content, $mimeType);
}

if( isset($_POST['action']) && $_POST['action'] == "delete_file" && isset($_POST['FilePath']) ) {
   // check if the file can found without redirection
   if( file_exists($_POST['FilePath']) ) {
      $fileUtils->deleteFile( $_POST['FilePath'] );

      // redirect outside the utils folder, especially when running via ajax
   } else if( file_exists( kan_fix_path($_POST['FilePath']) ) ) {
      $fileUtils->deleteFile( kan_fix_path($_POST['FilePath']) );

   }
}

class FileUtils {

   public $mimeTypes = array(
      "js" => "text/javascript",
      "css" => "text/css",
      "php" => "text/php",
      "html" => "text/html",
      "htm" => "text/html",
      "xml" => "text/xml",
	  "json" => "text/javascript"
   );

   public $webExtensions = array(
      "js" => "javascript",
      "css" => "css",
      "php" => "php",
      "html" => "html",
      "htm" => "html",
      "xml" => "xml",
      "gif" => "gif",
      "jpg" => "jpg",
      "png" => "png",
      "swf" => "swf",
	  "json" => "json"
   );

   public function printScripts() { ?>
        <link type="text/css" href="../cms/utils/file_utils.css" rel="stylesheet" />
        <script type="text/javascript" src="../cms/utils/file_utils.js"></script>
        <script type="text/javascript" src="../cms/scripts/code_mirror/js/codemirror.js"></script>
        <?php
   }

   public function getFileEditInfo($filePath, $mimeType = 'text/php') {

	  $file_type = is_dir($filePath) ? "Folder" : "File";

      if( is_writable($filePath) ) {
         echo "<span class='cms-file-writable'>$file_type Is Writable</span>";
		 
		 if( !is_dir($filePath) ) {
            echo " | <a href=\"javascript:file_utils.showOverlayedEditor('$filePath', '$mimeType');\">Edit File</a>";
		 }
      } else {
         echo "<span class='cms-file-readonly'>File Is Readonly</span>";
      }
   }

   public function saveFileContent($filePath, $contentData) {

      if( is_writable($filePath) ) {
         $data = stripslashes($contentData); // remove possible escaped characters
         $data = htmlentities($data); // encode the data as HTML

         file_put_contents( $filePath, "" . html_entity_decode($data) . "" );
      }
   }

   public function generateFolderTree($folder) {
      if( $folder == '' || $folder == NULL ) {
         return;
      }

      $dirname = basename($folder);
      echo "<div id='dir_tree' class='dir_tree'>\n";
      echo "<ul class='dir_group'><li class='dir_name'>"
         . "<div >"
         . "  <div class='name_col'><span>$dirname</span></div>"
         . "  <!--<div class='options_col'><a href='#'>Add</a> | <a href='#'>Delete</a></div>--> "
         . "</div>";
      $this->traverseDirTree($folder, FALSE);
      echo "</li></ul>\n";
      echo "</div>\n"; ?>

      <script type="text/javascript">
         pageManager.addLoadEvent( file_utils.attachFolderHandlers );
      </script><?php
   }


   public function traverseDirTree($path = '.', $isSub = TRUE) {
      $handle = opendir($path);
      
      if ( $handle )  {
         $collapsed = ($isSub == TRUE) ? "collapsed" : "expanded";
         echo "<ul class='dir_group $collapsed'>";

         $queuedir = array();
         $queuefile = array();

         while (false !== ($file = readdir($handle))) {
            if (is_dir($path.$file) && $file != '.' && $file !='..')
               $queuedir[] = $file;
            else if ($file != '.' && $file !='..')
               $queuefile[] = $file;
         }

         sort($queuedir);
         sort($queuefile);

         $this->printSubDir($queuedir, $path);
         $this->printQueue($queuefile, $path);

         echo "</ul>";
      }
   }

   private function printSubDir($queue, $path) {
      foreach ($queue as $dir) {
         echo "<li class='dir_name'>"
            . "<div >"
            . "  <div class='name_col'><span>$dir</span></div>"
            . "	<!--<div class='options_col'>Add | Delete</div>-->"
            . "</div>";
         $this->traverseDirTree($path.$dir."/");
         echo "</li>";
      }
   }

   private function printQueue($queue, $path) {
      foreach ($queue as $file) {
         $filePath = $path.$file;
         $extension = substr($file, strrpos($file,".") + 1);

         // if file is writable and file type is editable
         if( is_writable($filePath) && array_key_exists($extension, $this->mimeTypes) ) {
            $mimeType = $this->mimeTypes[$extension];
            echo "<li class='file_name'>"
               . "<div class='name_col'>"
               . "  <a href=\"javascript:file_utils.showOverlayedEditor('$filePath', '$mimeType'); \">$file</a>"
               . "</div>"
               . "<div class='options_col'>"
               . "  <a href=\"javascript:file_utils.showOverlayedEditor('$filePath', '$mimeType'); \">Edit</a> | "
               . "  <a href=\"#\" onclick=\"file_utils.deleteFile('$filePath', this); return false;\">Delete</a> "
               . "</div>"
               . "</li>";

            // if is web related document
         } else if( array_key_exists($extension, $this->webExtensions) ) {
            echo "<li class='file_name'>$file</li>";
         } else {
            //echo "<li class='file_name'>$file</li>";
         }
      }
   }

   public function deleteFile($filePath, $canRemoveDir = false) {
      if( file_exists($filePath) ) {
         if( is_dir($filePath) && $canRemoveDirr ) {
            $this->rmdirr($filePath);
         } else {
            unlink($filePath);
         }
      }
   }

   public function rmdirr($dirname) {
      // Sanity check
      if (!file_exists($dirname)) {
         return false;
      }

      // Simple delete for a file
      if (is_file($dirname)) {
         return unlink($dirname);
      }

      // Loop through the folder
      $dir = dir($dirname);
      while (false !== $entry = $dir->read()) {
         // Skip pointers
         if ($entry == '.' || $entry == '..') {
            continue;
         }

         // Recurse
         $this->rmdirr("$dirname/$entry");
      }

      // Clean up
      $dir->close();
      return rmdir($dirname);
   }

   public function getEditorForContent($content = '', $mimeType = 'text/php') {
      if( $content == '' ) {
         $content .= "<?php \n";
         $content .= "   //TODO: your PHP code goes here\n";
         $content .= "?>";
      } ?>

      <div style="height: 520px; position: relative; overflow: hidden;">
         <textarea cols="10" rows="3" id='EditorContent' name='EditorContent' style="width: 100%; height: 100%;"><?php echo $content; ?></textarea>
         
         <script type="text/javascript">
		 	pageManager.addLoadEvent( function() {
				file_utils.codeEditor = CodeMirror.fromTextArea('EditorContent', {
					
					parserfile: ["parsexml.js", "parsecss.js", "tokenizejavascript.js", "parsejavascript.js", "parsehtmlmixed.js",
								 "../contrib/php/js/tokenizephp.js", "../contrib/php/js/parsephp.js",
								 "../contrib/php/js/parsephphtmlmixed.js"],
					stylesheet: ["../cms/scripts/code_mirror/css/xmlcolors.css", 
								 "../cms/scripts/code_mirror/css/jscolors.css", 
								 "../cms/scripts/code_mirror/css/csscolors.css", 
								 "../cms/scripts/code_mirror/contrib/php/css/phpcolors.css"],
					path: "../cms/scripts/code_mirror/js/",
					continuousScanning: 500,
					textWrapping: false
				});	
			});         	
         </script>
      </div><?php
   }
   
   
   public function extractZipArchive($filePath, $destFolder = '') {
		// create object
		$zip = new ZipArchive() ;
		
		// open archive
		if ($zip->open( $destZipFile ) !== TRUE) {
			die ('Could not open archive');
		}
		
		// if the destFolder is not supplied, then we'll need to extract the file to
		// same directory.
		if( $destFolder == '') {
			$destFolder = dirname($filePath);	
		}
		
		// extract contents to destination directory
		$zip->extractTo($destFolder);
		
		// close archive
		$zip->close();   
   }
   
   /** 
     * Copy file or folder from source to destination, it can do 
     * recursive copy as well and is very smart 
     * It recursively creates the dest file or directory path if there weren't exists 
     * Situtaions : 
     * - Src:/home/test/file.txt ,Dst:/home/test/b ,Result:/home/test/b -> If source was file copy file.txt name with b as name to destination 
     * - Src:/home/test/file.txt ,Dst:/home/test/b/ ,Result:/home/test/b/file.txt -> If source was file Creates b directory if does not exsits and copy file.txt into it 
     * - Src:/home/test ,Dst:/home/ ,Result:/home/test/** -> If source was directory copy test directory and all of its content into dest      
     * - Src:/home/test/ ,Dst:/home/ ,Result:/home/**-> if source was direcotry copy its content to dest 
     * - Src:/home/test ,Dst:/home/test2 ,Result:/home/test2/** -> if source was directoy copy it and its content to dest with test2 as name 
     * - Src:/home/test/ ,Dst:/home/test2 ,Result:->/home/test2/** if source was directoy copy it and its content to dest with test2 as name 
     * @todo 
     *     - Should have rollback technique so it can undo the copy when it wasn't successful 
     *  - Auto destination technique should be possible to turn off 
     *  - Supporting callback function 
     *  - May prevent some issues on shared enviroments : http://us3.php.net/umask 
     * @param $source //file or folder 
     * @param $dest ///file or folder 
     * @param $options //folderPermission,filePermission 
     * @return boolean 
     */ 
   public function smartCopy($source, $dest, $options=array('folderPermission'=>0755,'filePermission'=>0755)) 
    { 
        $result=false; 
        
        if (is_file($source)) { 
            if ($dest[strlen($dest)-1]=='/') { 
                if (!file_exists($dest)) { 
                    cmfcDirectory::makeAll($dest,$options['folderPermission'],true); 
                } 
                $__dest=$dest."/".basename($source); 
            } else { 
                $__dest=$dest; 
            } 
            $result=copy($source, $__dest); 
            chmod($__dest,$options['filePermission']); 
            
        } elseif(is_dir($source)) { 
            if ($dest[strlen($dest)-1]=='/') { 
                if ($source[strlen($source)-1]=='/') { 
                    //Copy only contents 
                } else { 
                    //Change parent itself and its contents 
                    $dest=$dest.basename($source); 
                    @mkdir($dest); 
                    chmod($dest,$options['filePermission']); 
                } 
            } else { 
                if ($source[strlen($source)-1]=='/') { 
                    //Copy parent directory with new name and all its content 
                    @mkdir($dest,$options['folderPermission']); 
                    chmod($dest,$options['filePermission']); 
                } else { 
                    //Copy parent directory with new name and all its content 
                    @mkdir($dest,$options['folderPermission']); 
                    chmod($dest,$options['filePermission']); 
                } 
            } 

            $dirHandle=opendir($source); 
            while($file=readdir($dirHandle)) 
            { 
                if($file!="." && $file!="..") 
                { 
                     if(!is_dir($source."/".$file)) { 
                        $__dest=$dest."/".$file; 
                    } else { 
                        $__dest=$dest."/".$file; 
                    } 
                    //echo "$source/$file ||| $__dest<br />"; 
                    $result = $this->smartCopy($source."/".$file, $__dest, $options); 
                } 
            } 
            closedir($dirHandle); 
            
        } else { 
            $result=false; 
        } 
        return $result; 
    }
	
	public function encodeUrlParam ( $string ) {
	  $string = trim($string);
		
	  if ( ctype_digit($string) ) {
		return $string;
		
	  } else {      
		// replace accented chars
		$accents = '/&([A-Za-z]{1,2})(grave|acute|circ|cedil|uml|lig);/';
		$string_encoded = htmlentities($string,ENT_NOQUOTES,'UTF-8');
	
		$string = preg_replace($accents,'$1',$string_encoded);
		  
		// clean out the rest
		$replace = array('([\40])','([^a-zA-Z0-9-])','(-{2,})');
		$with = array('-','','-');
		$string = preg_replace($replace,$with,$string); 
	  } 
	
	  return strtolower($string);
	}
}
?>
